#include "Protect.h"

#define  MIN_SAMPLE_TEMP        (-40)
#define  MAX_SAMPLE_TEMP        (125)
#define  NTC_POINT              (166)

#define HW_OVR_CUR_THREHOLD (5)

uint8_t currrentTempValue = 0;//当前温度值
uint16_t vBusTimes10 = 0;//Vbus电压乘以10后的值
uint8_t pwmTimerBreakFlag = 0;
uint8_t pwmTimerBreakCnt = 0;//PWM刹车触发计数器

uint32_t protectFaultBitMap = 0;
uint16_t protectFaultBitMap_LowWord = 0;
uint16_t protectFaultBitMap_HighWord = 0;

uint16_t vBusOverCnt;
uint16_t vBusLowCnt;
uint16_t softOvrCurrentCnt;

//温敏电阻采样值表，第一个是-40度，最后一个是125度
const unsigned short TempTable[166] = 
{
    4061,	4058,	4056,	4053,	4050,	4047,	4044,	4040,	4036,	4033,
    4029,	4024,	4020,	4015,	4010,	4005,	3999,	3993,	3987,	3981,
    3974,	3967,	3960,	3952,	3944,	3935,	3926,	3917,	3907,	3897,
    3886,	3875,	3864,	3852,	3839,	3826,	3812,	3798,	3784,	3768,
    3752,	3736,	3719,	3701,	3683,	3664,	3645,	3625,	3604,	3582,
    3560,	3538,	3514,	3490,	3465,	3440,	3414,	3387,	3360,	3332,
    3303,	3274,	3244,	3214,	3182,	3151,	3119,	3086,	3052,	3018,
    2984,	2949,	2914,	2878,	2842,	2806,	2769,	2731,	2694,	2656,
    2618,	2580,	2541,	2503,	2464,	2425,	2386,	2348,	2309,	2270,
    2231,	2192,	2153,	2115,	2076,	2038,	2000,	1963,	1925,	1888,
    1851,	1814,	1778,	1742,	1706,	1672,	1637,	1603,	1569,	1535,
    1503,	1470,	1438,	1407,	1375,	1345,	1315,	1286,	1256,	1228,
    1200,	1173,	1146,	1119,	1093,	1068,	1043,	1019,	995,	971,
    948,	926,	904,	883,	862,	841,	821,	802,	783,	764,
    746,	728,	710,	693,	677,	661,	645,	629,	614,	600,
    585,	571,	558,	544,	532,	519,	507,	495,	482,	475,
    460,	449,	439,	429,	419,	409				
};

void protectSetFaultBit(FaultBit_t bit)
{
    U32SetBit(protectFaultBitMap,bit);
}

void protectUpdateVbus(void)
{
    uint16_t vBusAdcValue = u16AdcGetAverageValue(AN_DEF_VBUS);
    vBusTimes10 = 5282 * vBusAdcValue >> 16;//10*vBus = 0.0806 * vBusAdcValue
}

//根据当前采样值获得温度表索引值
static uint16_t getCurrentTempIndex(uint16_t adcValue)
{
    uint16_t index = 0;

    if( adcValue>TempTable[0] ){
        return 0;
    }else if( adcValue<TempTable[NTC_POINT - 1] ){
        return NTC_POINT - 1;        
    }

    for( index=0; index<NTC_POINT; index++)
    {
        if( TempTable[index+1] < adcValue){
            break;
        }
    }

    return index;
}

//检测硬件过流状态
void protectHwOverCurrentMonitor(void)
{
    if( TIM1->SR & (1<<7) ) //BIF = 1
    {
        U32ClearBit(TIM1->SR,7);
        pwmTimerBreakCnt++;
        if( pwmTimerBreakCnt >= HW_OVR_CUR_THREHOLD )
        {
            U32SetBit(protectFaultBitMap,Fault_HW_OVR_CURRENT);//写故障码
            U32SetBit(protectFaultBitMap,Fault_HW_OVR_CURRENT_Happen);//写故障码            
            pwmTimerBreakCnt = 0;
        }
    }
    else
    {
        if(pwmTimerBreakCnt)
            pwmTimerBreakCnt--;
        else
            U32ClearBit(protectFaultBitMap,Fault_HW_OVR_CURRENT_Happen);//清除故障码 
    }
}

//更新温度
void protectUpdateTemp(void)
{
    static uint8_t tempUpdateCnt = 0;
    static uint16_t currentTempIndex = 0;
    uint16_t tempAdcValue = u16AdcGetAverageValue(AN_DEF_NTC);

    if( tempUpdateCnt < 8 )//温度初始化
    {
        currentTempIndex += getCurrentTempIndex(tempAdcValue);
        if( ++tempUpdateCnt >= 8 ){
            currentTempIndex = currentTempIndex>>3;//上电判断8次取平均，位移代替除法
        }
    }
    else//初始化完成
    {   
        if( tempAdcValue>=TempTable[0] )
        {
            currentTempIndex = 0;
        }
        else if( tempAdcValue<=TempTable[NTC_POINT - 1] )
        {
            currentTempIndex = NTC_POINT - 1;        
        }
        else
        {
            if( tempAdcValue>TempTable[currentTempIndex] )//新温度小于当前温度，往前找
            {
                for( uint16_t idx = currentTempIndex ; tempAdcValue > TempTable[idx]; idx-- )
                {
                    currentTempIndex = idx;
                }
            }
            else if( tempAdcValue<TempTable[currentTempIndex] )//新温度大于当前温度，往后找
            {
                for( uint16_t idx = currentTempIndex ; tempAdcValue < TempTable[idx+1]; idx++ )
                {
                    currentTempIndex = idx;
                }
            }
            else
            {
                /*do nothing*/
            }
        }

        currrentTempValue = currentTempIndex + MIN_SAMPLE_TEMP;
    }
}

void protectProcess(void)
{
    uint16_t VBUS = vBusTimes10;
    uint16_t IBUS = u16AdcGetAverageValue(AN_DEF_IBUS);
    MotorState_t eMotorState = eMotorGetState();
    protectUpdateVbus();
    protectUpdateTemp();
    protectHwOverCurrentMonitor();
    if(eMotorState == MotorStRun)
    {
        //堵转电流保护
        if( g_LockCurrentCnt==0 && IBUS>=136 ){
            U32SetBit(protectFaultBitMap,Fault_LOCK_CURRENT);//写故障码
        }
        //堵转相位保护
        if(g_LockPhaseCnt==0){
            U32SetBit(protectFaultBitMap,Fault_LOCK_PHASE);//写故障码        
        }        
    }

    //软件过流保护
    if( IBUS >= SOFT_OVR_CUR_THRESHOLD )
    {
        if( softOvrCurrentCnt >= SOFT_OVR_CUR_TIME_THRESHOLD )
        {
            U32SetBit(protectFaultBitMap,Fault_SOFT_OVR_CURRENT);//写故障码            
        }
        else
        {
            softOvrCurrentCnt++;
        }
    }
    else
    {
        softOvrCurrentCnt = 0;
    }

    //过欠压保护
    if( VBUS >= VBUS_OVR_THRESHOLD )//过压
    {
        if( vBusOverCnt>=VBUS_OVR_TIME_THRESHOLD )
        {
            U32SetBit(protectFaultBitMap,Fault_Vbus_OVER);               
        }
        else
        {
            vBusOverCnt++;
        }
    }
    else if( VBUS <= VBUS_LOW_THRESHOLD )//欠压
    {
        if( vBusLowCnt>=VBUS_LOW_TIME_THRESHOLD )
        {
            U32SetBit(protectFaultBitMap,Fault_Vbus_LOW);               
        }
        else
        {
            vBusLowCnt++;
        }
    }
    else if( (VBUS >= VBUS_LOW_THRESHOLD + VBUS_LOW_WINDOW) && (VBUS <= VBUS_OVR_THRESHOLD - VBUS_OVR_WINDOW) )
    {
        U32ClearBit(protectFaultBitMap,Fault_Vbus_OVER);        
        U32ClearBit(protectFaultBitMap,Fault_Vbus_LOW);
    }

    protectFaultBitMap_LowWord = U32GetLowWord(protectFaultBitMap);
    protectFaultBitMap_HighWord = U32GetHighWord(protectFaultBitMap);    
}

